package com.zbkj.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.zbkj.dal.entity.ba.Booking;
import com.zbkj.dal.entity.merchant.Merchant;
import com.zbkj.dal.pojo.request.PageParamRequest;
import com.zbkj.dal.pojo.request.ba.ConfirmRequest;
import com.zbkj.dal.pojo.request.ba.CreateBookingRequest;
import com.zbkj.dal.pojo.request.ba.QueryBookingRequest;
import com.zbkj.dal.pojo.response.ba.BookingResponse;
import com.zbkj.dal.common.utils.SecurityUtil;
import com.zbkj.dal.dao.BookingMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.service.service.BookingService;
import com.zbkj.service.service.MerchantService;
import com.zbkj.service.service.SystemAdminService;
import com.zbkj.service.service.UserService;
import com.zbkj.service.util.UserUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 卡座预约 服务实现类
 * </p>
 *
 * @author jhui
 * @since 2023-10-03
 */
@Service
public class BookingServiceImpl extends ServiceImpl<BookingMapper, Booking> implements BookingService {
    @Autowired
    private UserService userService;
    @Autowired
    private MerchantService merchantService;
    @Autowired
    private SystemAdminService adminService;
    @Resource
    private AliSmsServiceImpl aliSmsService;

    @Override
    public List<BookingResponse> listMyBooking(Integer status, PageParamRequest pageParamRequest) {
        List<BookingResponse> bookingResponses = Lists.newArrayList();
        Integer userId = userService.getUserIdException();
        LambdaQueryWrapper<Booking> queryWrapper = Wrappers.lambdaQuery(Booking.class);
        queryWrapper.eq(Booking::getUid, userId);
        if (status != null && status != -1) {
            queryWrapper.eq(Booking::getStatus, status);
        }
        queryWrapper.orderByDesc(Booking::getId);
        queryWrapper.last("LIMIT " + (pageParamRequest.getPage() - 1) * pageParamRequest.getLimit() + "," + pageParamRequest.getLimit());
        List<Booking> list = list(queryWrapper);

        if (CollectionUtils.isEmpty(list)) {
            return bookingResponses;
        }
        for (Booking booking : list) {
            BookingResponse bookingResponse = new BookingResponse();
            BeanUtils.copyProperties(booking, bookingResponse);
            bookingResponses.add(bookingResponse);
        }
        List<Integer> merIds = list.stream().filter(p -> p.getMerId() != null).map(m -> m.getMerId()).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(merIds)) {
            List<Merchant> merchantList = merchantService.getListByIdList(merIds);
            for (BookingResponse dto : bookingResponses) {
                if (dto.getMerId() == null) {
                    continue;
                }
                merchantList.stream().filter(p -> ObjectUtils.nullSafeEquals(p.getId(), dto.getMerId())).findFirst()
                        .ifPresent(c -> {
                            dto.setMerName(c.getName());
                        });
            }
        }
        return bookingResponses;
    }

    @Override
    public Boolean deleteMyBooking(Integer id) {
        Integer userId = userService.getUserIdException();
        LambdaQueryWrapper<Booking> queryWrapper = Wrappers.lambdaQuery(Booking.class);
        queryWrapper.eq(Booking::getId, id).eq(Booking::getStatus, 0).eq(Booking::getUid, userId);
        return this.remove(queryWrapper);
    }

    @Override
    public Boolean create(CreateBookingRequest createBookingRequest) {
        Integer userId = userService.getUserIdException();
        Booking booking = new Booking();
        BeanUtils.copyProperties(createBookingRequest, booking);
        booking.setUid(userId);
        booking.setStatus(0);
        booking.setCreateTime(LocalDateTime.now());
        booking.setUpdateTime(LocalDateTime.now());
        Boolean isOK = save(booking);
        if (isOK) {
            //发送短信
            aliSmsService.sendAttractMsg("卡座预约");
        }

        return isOK;
    }

    @Override
    public BookingResponse detail(Integer id) {
        Booking booking = getById(id);
        BookingResponse bookingResponse = new BookingResponse();
        BeanUtils.copyProperties(booking, bookingResponse);
        if (bookingResponse.getMerId() != null) {
            Merchant merchant = merchantService.getById(bookingResponse.getMerId());
            bookingResponse.setMerName(merchant.getName());
        }
        return bookingResponse;
    }

    @Override
    public PageInfo<BookingResponse> queryBookings(QueryBookingRequest queryBookingRequest, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<Booking> queryWrapper = Wrappers.lambdaQuery(Booking.class);
        if (queryBookingRequest.getStatus() != null) {
            queryWrapper.eq(Booking::getStatus, queryBookingRequest.getStatus());
        }
        if (queryBookingRequest.getBeginDate() != null) {
            queryWrapper.ge(Booking::getCreateTime, queryBookingRequest.getBeginDate());
        }
        if (queryBookingRequest.getEndDate() != null) {
            queryWrapper.lt(Booking::getCreateTime, queryBookingRequest.getEndDate().plusDays(1));
        }
        queryWrapper.orderByDesc(Booking::getId);
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<Booking> list = this.list(queryWrapper);
        PageInfo<Booking> pageInfo = PageInfo.of(list);
        PageInfo<BookingResponse> result = new PageInfo<>();
        result.setTotal(pageInfo.getTotal());
        List<BookingResponse> dtos = Lists.newArrayList();
        for (Booking booking : pageInfo.getList()) {
            BookingResponse bookingResponse = new BookingResponse();
            BeanUtils.copyProperties(booking, bookingResponse);
            dtos.add(bookingResponse);
        }
        result.setList(dtos);
        UserUtils.fillUsers(result.getList());
        if (CollectionUtils.isNotEmpty(dtos)) {
            List<Integer> merIds = dtos.stream().filter(p -> p.getMerId() != null).map(m -> m.getMerId()).distinct().collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(merIds)) {
                List<Merchant> merchantList = merchantService.getListByIdList(merIds);
                for (BookingResponse dto : dtos) {
                    merchantList.stream().filter(p -> ObjectUtils.nullSafeEquals(p.getId(), dto.getMerId())).findFirst()
                            .ifPresent(c -> {
                                dto.setMerName(c.getName());
                            });
                }
            }

            List<Integer> operatorIds = dtos.stream().filter(p -> p.getOperatorId() != null).map(m -> m.getOperatorId()).distinct().collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(operatorIds)) {
                Map<Integer, String> nameMapByIdList = adminService.getNameMapByIdList(operatorIds);
                for (BookingResponse dto : dtos) {
                    if (dto.getOperatorId() != null) {
                        dto.setOperatorName(nameMapByIdList.get(dto.getOperatorId()));
                    }
                }
            }
        }
        return result;
    }

    @Override
    public Boolean confirm(ConfirmRequest confirmRequest) {
        Integer id = SecurityUtil.getLoginUserVo().getUser().getId();
        confirmRequest.setOperatorId(id);
        LambdaUpdateWrapper<Booking> updateWrapper = Wrappers.lambdaUpdate(Booking.class);
        updateWrapper
                .set(Booking::getBeginTime, confirmRequest.getBeginTime())
                .set(Booking::getEndTime, confirmRequest.getEndTime())
                .set(Booking::getStatus, confirmRequest.getStatus())
                .set(Booking::getRemark, confirmRequest.getRemark())
                .set(Booking::getOperatorId, confirmRequest.getOperatorId())
                .eq(Booking::getId, confirmRequest.getId());
        return update(updateWrapper);
    }
}
